package com.qcby.aspect;

import com.qcby.annotation.RepeatSubmit;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@Aspect
public class RepeatSubmitAspect {

    private static final String TOKEN = "token";

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Around("@annotation(repeatSubmit)")
    private Object doAround(ProceedingJoinPoint joinPoint, RepeatSubmit repeatSubmit) {
        HttpServletRequest request = Objects.requireNonNull(getRequestAttributes()).getRequest();
        // 获取访问路径
        String uri = request.getRequestURI();
        // 获取唯一标识符
        String token = request.getParameter(TOKEN);
        //获取缓存中的数据
        String value = redisTemplate.opsForValue().get(token);
        //判断缓存中是否存在
        if (uri.equals(value)) {
            return repeatSubmit.msg();
        } else {
            //不存在，放行请求,并设置缓存
            redisTemplate.opsForValue().set(token, uri, repeatSubmit.time(), TimeUnit.MILLISECONDS);
        }
        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        return proceed;
    }


    public static ServletRequestAttributes getRequestAttributes() {
        try {
            RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
            return (ServletRequestAttributes) attributes;
        } catch (Exception e) {
            return null;
        }
    }
}